module klang.编译.输出注释.输出注释_;
import 全局;
import std.functional: ·fd = toDelegate;
import ··类型_ = klang.编译.类型.类型_;
import klang.编译.核心.核心_: 整数_, 过滤, 最小, 裁剪文本, 循环每个, 返回零值, 创建数组, 查找数组索引, 是空白或换行;
import klang.编译.类型.枚举值.枚举值_: 字符_, TK, SK;
import klang.编译.类型.类型_: 文本范围_, 注释范围_, 源映射范围_, SourceMapGenerator;
import klang.编译.输出工具.输出工具_: 打印机基础环境_;
import klang.编译.语法节点.节点_: 分离注释信息_, 节点_, 源文件_, nodeIsSynthesized;
import klang.编译.扫描工具.扫描工具_: 获取扫描工具当前目标, 恢复原扫描工具环境, 设置扫描工具环境, 循环每个前方注释范围_1, 循环每个前方注释范围_2, 循环每个尾随注释范围_1, 获取前方注释范围组, 计算位置的行和列, 获取位置的行和列, 计算行开始组, 获取行开始组, 跳过杂项;
import klang.编译.输出节点.输出节点_: getSyntheticTrailingComments, getSyntheticLeadingComments, getOrCreateEmitNode, getOriginalNode_1, getCommentRange, getEmitFlags, EmitFlags, 合成注释_, 输出节点_, getSourceMapRange, setSourceMapRange;
import klang.编译.路径.路径_: 文件扩展名是;
alias 写注释函数类型_ = void delegate(dstring, long[], long, long, dstring);
打印机基础环境_ _基础环境;
TK 原扫描工具目标;
void 初始输出注释环境(打印机基础环境_ 环境) {
    ._基础环境 = 环境;
    .原扫描工具目标 = 获取扫描工具当前目标();
    设置扫描工具环境(环境.目标, 环境.单行注释头, 环境.多行注释头, 环境.多行注释尾);
}
void 恢复输出注释环境() {
    恢复原扫描工具环境(.原扫描工具目标, _基础环境.目标);
    .原扫描工具目标 = TK.无_;
}
void emitComments(dstring text, long[] lineMap, 注释范围_[] comments = ··null!(注释范围_[]), bool leadingSeparator = ··null!(bool), bool trailingSeparator = ··null!(bool), dstring newLine = ··null!(dstring), void delegate(dstring, long[], long, long, dstring) writeComment = ··null!(void delegate(dstring, long[], long, long, dstring))) {
    if ((comments !is ··null!(注释范围_[])) && comments.length > 0) {
        if (leadingSeparator) {
            _基础环境.writer.writeSpace(" "d);
        }
        bool emitInterveningSeparator = false;
        foreach (注释范围_ comment; comments) {
            if (emitInterveningSeparator) {
                _基础环境.writer.writeSpace(" "d);
                emitInterveningSeparator = false;
            }
            writeComment(text, lineMap, comment.开始, comment.结束, _基础环境.newLine);
            if (comment.有尾随新行) {
                _基础环境.writer.writeLine();
            }
            else {
                emitInterveningSeparator = true;
            }
        }
        if (emitInterveningSeparator && trailingSeparator) {
            _基础环境.writer.writeSpace(" "d);
        }
    }
}
void emitNewLineBeforeLeadingComments(long[] lineMap, 文本范围_ node, 注释范围_[] leadingComments = ··null!(注释范围_[])) {
    .emitNewLineBeforeLeadingCommentsOfPosition(lineMap, node.开始, leadingComments);
}
void emitNewLineBeforeLeadingCommentsOfPosition(long[] lineMap, long 开始, 注释范围_[] leadingComments = ··null!(注释范围_[])) {
    // If the leading comments start on different line than the start of node, write new line
    if ((leadingComments !is ··null!(注释范围_[])) && (leadingComments.length !is ··null!(size_t)) && 开始 != leadingComments[0].开始 && 计算位置的行和列(lineMap, 开始).行 != 计算位置的行和列(lineMap, leadingComments[0].开始).行) {
        _基础环境.writer.writeLine();
    }
}
/**
 * Detached comment is a comment at the top 属于 file or 函数 body that is separated from
 * the next statement by space.
 */
分离注释信息_ emitDetachedComments(dstring text, long[] lineMap, 写注释函数类型_ writeComment, 文本范围_ node, dstring newLine, bool removeComments) {
    bool delegate(注释范围_) isPinnedCommentLocal;
    注释范围_[] leadingComments;
    分离注释信息_ currentDetachedCommentInfo;
    bool isPinnedCommentLocal·func(注释范围_ comment) {
        return .isPinnedComment(text, comment.开始);
    }
    isPinnedCommentLocal = &isPinnedCommentLocal·func;
    if (removeComments) {
        // removeComments is 真, only reserve pinned comment at the top 属于 file
        // For example:
        //      /*! Pinned Comment */
        //
        //      var x = 10;
        if (node.开始 == 0) {
            注释范围_[] 前方 = 获取前方注释范围组(text, node.开始);
            if (前方 !is ··null!(注释范围_[])) {
                leadingComments = 过滤!(注释范围_)(前方, cast(bool delegate(注释范围_))(isPinnedCommentLocal));
            }
        }
    }
    else {
        // removeComments is 假, just get detached as normal and bypass the process to 过滤 comment
        leadingComments = 获取前方注释范围组(text, node.开始);
    }
    if (leadingComments !is ··null!(注释范围_[])) {
        注释范围_[] detachedComments = [];
        注释范围_ lastComment;
        foreach (注释范围_ comment; leadingComments) {
            if (lastComment !is ··null!(注释范围_)) {
                long lastCommentLine = 计算位置的行和列(lineMap, lastComment.结束).行;
                long commentLine = 计算位置的行和列(lineMap, comment.开始).行;
                if (commentLine >= lastCommentLine + 2) {
                    // There was a blank line between the last comment and this comment.  This
                    // comment is not part 属于 the copyright comments.  Return what we have so
                    // far.
                    break;
                }
            }
            .追加!(注释范围_)(detachedComments, comment);
            lastComment = comment;
        }
        if (detachedComments.length > 0) {
            // All comments look like they could have been part 属于 the copyright header.  Make
            // sure there is at least one blank line between it and the node.  If not, it's not
            // a copyright header.
            long lastCommentLine = 计算位置的行和列(lineMap, detachedComments[detachedComments.length - 1].结束).行;
            long nodeLine = 计算位置的行和列(lineMap, 跳过杂项(text, node.开始)).行;
            if (nodeLine >= lastCommentLine + 2) {
                // Valid detachedComments
                .emitNewLineBeforeLeadingComments(lineMap, node, leadingComments);
                .emitComments(text, lineMap, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, _基础环境.newLine, cast(void delegate(dstring, long[], long, long, dstring))(writeComment));
                currentDetachedCommentInfo = new 分离注释信息_(node.开始, detachedComments[detachedComments.length - 1].结束);
            }
        }
    }
    return currentDetachedCommentInfo;
}
bool isPinnedComment(dstring text, long start) {
    return text.length > start + 2 && text[start + 1] == 字符_.星号 && text[start + 2] == 字符_.叹号;
}
void writeCommentRange(dstring text, long[] lineMap, long commentPos, long commentEnd, dstring newLine) {
    if (text[commentPos + 1] == 字符_.星号) {
        ··类型_.行和列_ firstCommentLineAndCharacter = 计算位置的行和列(lineMap, commentPos);
        size_t lineCount = lineMap.length;
        long firstCommentLineIndent = -1;
        {
            long 开始 = commentPos;
            long currentLine = firstCommentLineAndCharacter.行;
            for (; 开始 < commentEnd; ++currentLine) {
                long nextLineStart = (currentLine + 1) == lineCount ? text.length + 1 : lineMap[currentLine + 1];
                if (开始 != commentPos) {
                    // If we are not emitting first line, we need to write the spaces to adjust the alignment
                    if (firstCommentLineIndent == -1) {
                        firstCommentLineIndent = .calculateIndent(text, lineMap[firstCommentLineAndCharacter.行], commentPos);
                    }
                    // These are 整数_ 属于 spaces _基础环境.writer is going to write at current indent
                    long currentWriterIndentSpacing = _基础环境.writer.getIndent() * _基础环境.writer.getIndentSize();
                    // Number 属于 spaces we want to be writing
                    // eg: Assume _基础环境.writer indent
                    // module m {
                    //         /* starts at character 9 this is line 1
                    //    * starts at character 开始 4 line                        --1  = 8 - 8 + 3
                    //   More left indented comment */                            --2  = 8 - 8 + 2
                    //     class c { }
                    // }
                    // module m {
                    //     /* this is line 1 -- Assume current _基础环境.writer indent 8
                    //      * line                                                --3 = 8 - 4 + 5
                    //            More right indented comment */                  --4 = 8 - 4 + 11
                    //     class c { }
                    // }
                    long spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + .calculateIndent(text, 开始, nextLineStart);
                    if (spacesToEmit > 0) {
                        long numberOfSingleSpacesToEmit = spacesToEmit % _基础环境.writer.getIndentSize();
                        dstring indentSizeSpaceString = _基础环境.writer.getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / _基础环境.writer.getIndentSize());
                        // Write indent size 文本 ( in eg 1: = "", 2: "" , 3: 文本 with 8 spaces 4: 文本 with 12 spaces
                        _基础环境.writer.rawWrite(indentSizeSpaceString);
                        // Emit the single spaces (in eg: 1: 3 spaces, 2: 2 spaces, 3: 1 space, 4: 3 spaces)
                        while(numberOfSingleSpacesToEmit > 0) {
                            _基础环境.writer.rawWrite(" "d);
                            --numberOfSingleSpacesToEmit;
                        }
                    }
                    else {
                        // No spaces to emit write empty 文本
                        _基础环境.writer.rawWrite(""d);
                    }
                }
                // Write the comment line text
                .writeTrimmedCurrentLine(text, commentEnd, 开始, nextLineStart);
                开始 = nextLineStart;
            }
        }
    }
    else {
        // Single line comment 属于 style //....
        _基础环境.writer.writeComment(text[commentPos .. commentEnd]);
    }
}
void writeTrimmedCurrentLine(dstring text, long commentEnd, long 开始, long nextLineStart) {
    long 结尾 = 最小(commentEnd, nextLineStart - 1);
    dstring currentLineText = 裁剪文本(text[开始 .. 结尾]);
    if (currentLineText !is ··null!(dstring)) {
        // trimmed forward and ending spaces text
        _基础环境.writer.writeComment(currentLineText);
        if (结尾 != commentEnd) {
            _基础环境.writer.writeLine();
        }
    }
    else {
        // Empty 文本 - make sure we write empty line
        _基础环境.writer.rawWrite(_基础环境.newLine);
    }
}
long calculateIndent(dstring text, long 开始, long 结尾) {
    long currentLineIndent = 0;
    for (; 开始 < 结尾 && 是空白或换行(text[开始]); ++开始) {
        if (text[开始] == 字符_.水平制表) {
            // Tabs = TabSize = indent size and go to next tabStop
            currentLineIndent += _基础环境.writer.getIndentSize() - (currentLineIndent % _基础环境.writer.getIndentSize());
        }
        else {
            // Single space
            ++currentLineIndent;
        }
    }
    return currentLineIndent;
}
void emitCommentsBeforeNode(节点_ node, bool delegate(节点_) 停止回调) {
    EmitFlags emitFlags = getEmitFlags(node);
    文本范围_ commentRange = getCommentRange((cast(节点_)(node)));
    // Emit leading comments
    .emitLeadingCommentsOfNode(node, cast(bool delegate(节点_))(停止回调), emitFlags, commentRange.开始, commentRange.结束);
    if ((emitFlags & EmitFlags.NoNestedComments) != 0) {
        _基础环境.commentsDisabled = true;
    }
}
void emitCommentsAfterNode(节点_ node, long savedContainerPos, long savedContainerEnd, long savedDeclarationListContainerEnd) {
    EmitFlags emitFlags = getEmitFlags(node);
    文本范围_ commentRange = getCommentRange(node);
    // Emit trailing comments
    if ((emitFlags & EmitFlags.NoNestedComments) != 0) {
        _基础环境.commentsDisabled = false;
    }
    .emitTrailingCommentsOfNode(node, emitFlags, commentRange.开始, commentRange.结束, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd);
}
void emitLeadingCommentsOfNode(节点_ node, bool delegate(节点_) 停止回调, EmitFlags emitFlags, long 开始, long 结束) {
    _基础环境.hasWrittenComment = false;
    // We have to explicitly check that the node is JsxText because 如果 the compilerOptions.jsx is "preserve" we will not do any transformation.
    // It is expensive to walk entire tree just to set one 目标种类 of node to have no comments.
    bool skipLeadingComments = 开始 < 0 || (emitFlags & EmitFlags.NoLeadingComments) != 0;
    bool skipTrailingComments = 结束 < 0 || (emitFlags & EmitFlags.NoTrailingComments) != 0;
    // Save current container state on the stack.
    if ((开始 > 0 || 结束 > 0) && 开始 != 结束) {
        // Emit leading comments 如果 the position is not synthesized and the node
        // has not opted out from emitting leading comments.
        if (!skipLeadingComments) {
            .emitLeadingComments(开始, /*isEmittedNode*/ true);
        }
        if (!skipLeadingComments || (开始 >= 0 && (emitFlags & EmitFlags.NoLeadingComments) != 0)) {
            // Advance the container position 如果 comments get emitted or 如果 they've been disabled explicitly using NoLeadingComments.
            _基础环境.containerPos = 开始;
        }
        if (!skipTrailingComments || (结束 >= 0 && (emitFlags & EmitFlags.NoTrailingComments) != 0)) {
            // As above.
            _基础环境.containerEnd = 结束;
            // To avoid invalid comment emit in a down-level binding pattern, we
            // keep track of the last declaration list container's 结束
            if (停止回调(node)) {
                _基础环境.declarationListContainerEnd = 结束;
            }
        }
    }
    合成注释_[] 合成的前方注释组 = getSyntheticLeadingComments(node);
    if (合成的前方注释组 !is ··null!(合成注释_[])) {
        循环每个!(合成注释_, void*)(合成的前方注释组, (合成注释_ v, size_t i) {
            ((合成注释_ n, size_t _) { return .emitLeadingSynthesizedComment(n); })(v, i);
            return null;
        });
    }
}
void emitTrailingCommentsOfNode(节点_ node, EmitFlags emitFlags, long 开始, long 结束, long savedContainerPos, long savedContainerEnd, long savedDeclarationListContainerEnd) {
    bool skipTrailingComments = 结束 < 0 || (emitFlags & EmitFlags.NoTrailingComments) != 0;
    合成注释_[] 合成的尾随注释组 = getSyntheticTrailingComments(node);
    if (合成的尾随注释组 !is ··null!(合成注释_[])) {
        循环每个!(合成注释_, void*)(合成的尾随注释组, (合成注释_ v, size_t i) {
            ((合成注释_ x, size_t _) { return .emitTrailingSynthesizedComment(x); })(v, i);
            return null;
        });
    }
    if ((开始 > 0 || 结束 > 0) && 开始 != 结束) {
        // Restore previous container state.
        _基础环境.containerPos = savedContainerPos;
        _基础环境.containerEnd = savedContainerEnd;
        _基础环境.declarationListContainerEnd = savedDeclarationListContainerEnd;
        // Emit trailing comments 如果 the position is not synthesized and the node
        // has not opted out from emitting leading comments and is an emitted node.
        if (!skipTrailingComments) {
            .emitTrailingComments(结束);
        }
    }
}
void emitLeadingSynthesizedComment(合成注释_ comment) {
    if (comment.有前方新行 || comment.种类 == SK.单行注释) {
        _基础环境.writer.writeLine();
    }
    if (_基础环境.writer.getLine() > 0 && comment.前方新行数量 != 0) {
        int i = comment.前方新行数量;
        while(i != 0) {
            _基础环境.writer.writeLine(i > 0);
            --i;
        }
    }
    .writeSynthesizedComment(comment);
    if (comment.有尾随新行 || comment.种类 == SK.单行注释) {
        _基础环境.writer.writeLine();
    }
    else {
        _基础环境.writer.writeSpace(" "d);
    }
}
void emitTrailingSynthesizedComment(合成注释_ comment) {
    if (!_基础环境.writer.isAtStartOfLine()) {
        _基础环境.writer.writeSpace(" "d);
    }
    .writeSynthesizedComment(comment);
    if (comment.有尾随新行) {
        _基础环境.writer.writeLine();
    }
}
void writeSynthesizedComment(合成注释_ comment) {
    dstring 内容 = .formatSynthesizedComment(comment);
    long[] lineMap = comment.种类 == SK.多行注释 ? 计算行开始组(内容) : 返回零值!(long[])();
    .writeCommentRange(内容, lineMap, 0, 内容.length, _基础环境.newLine);
}
dstring formatSynthesizedComment(合成注释_ comment) {
    return comment.种类 == SK.多行注释 ? _基础环境.多行注释头 ~ comment.内容 ~ _基础环境.多行注释尾 : _基础环境.单行注释头 ~ comment.内容;
}
void emitBodyWithDetachedComments(节点_ node, 文本范围_ detachedRange, void delegate(节点_) emitCallback) {
    long 开始 = detachedRange.开始;
    long 结束 = detachedRange.结束;
    EmitFlags emitFlags = getEmitFlags(node);
    bool skipLeadingComments = 开始 < 0 || (emitFlags & EmitFlags.NoLeadingComments) != 0;
    bool skipTrailingComments = _基础环境.commentsDisabled || 结束 < 0 || (emitFlags & EmitFlags.NoTrailingComments) != 0;
    if (!skipLeadingComments) {
        .emitDetachedCommentsAndUpdateCommentsInfo(detachedRange);
    }
    if ((emitFlags & EmitFlags.NoNestedComments) != 0 && !_基础环境.commentsDisabled) {
        _基础环境.commentsDisabled = true;
        emitCallback(node);
        _基础环境.commentsDisabled = false;
    }
    else {
        emitCallback(node);
    }
    if (!skipTrailingComments) {
        .emitLeadingComments(detachedRange.结束, /*isEmittedNode*/ true);
        if (_基础环境.hasWrittenComment && !_基础环境.writer.isAtStartOfLine()) {
            _基础环境.writer.writeLine();
        }
    }
}
bool siblingNodePositionsAreComparable(节点_ previousNode, 节点_ nextNode, 节点_[] delegate(节点_) getContainingNodeArray) {
    if (nodeIsSynthesized(previousNode) || nodeIsSynthesized(nextNode)) {
        return false;
    }
    if (nextNode.开始 < previousNode.结束) {
        return false;
    }
    previousNode = (cast(节点_)(getOriginalNode_1(previousNode)));
    nextNode = (cast(节点_)(getOriginalNode_1(nextNode)));
    节点_ 父节点 = previousNode.父节点;
    if ((父节点 is ··null!(节点_)) || 父节点 != nextNode.父节点) {
        return false;
    }
    节点_[] parentNodeArray = getContainingNodeArray(previousNode);
    if (parentNodeArray !is ··null!(节点_[])) {
        long prevNodeIndex = 查找数组索引!(节点_)(parentNodeArray, (节点_ n) { return n == previousNode; });
        if (prevNodeIndex == -1) {
            return false;
        }
        long nextIndex = 查找数组索引!(节点_)(parentNodeArray, (节点_ n) { return n == nextNode; });
        if (nextIndex == -1) {
            return false;
        }
        return nextIndex == prevNodeIndex + 1;
    }
    return false;
}
void emitLeadingComments(long 开始, bool isEmittedNode) {
    _基础环境.hasWrittenComment = false;
    if (isEmittedNode) {
        .forEachLeadingCommentToEmit(开始, cast(void delegate(long, long, SK, bool, long))(·fd(&.emitLeadingComment)));
    }
}
long[] getCurrentLineMap() {
    if (_基础环境.currentLineMap !is ··null!(long[])) {
        return _基础环境.currentLineMap;
    }
    else if (_基础环境.currentSourceFile !is ··null!(源文件_)) {
        _基础环境.currentLineMap = 获取行开始组(_基础环境.currentSourceFile);
        return _基础环境.currentLineMap;
    }
    return ··null!(long[]);
}
long getLineOfLocalPositionFromLineMap(long[] lineMap, long pos) {
    return 计算位置的行和列(lineMap, pos).行;
}
void emitNewLineBeforeLeadingCommentOfPosition(long[] lineMap, long pos, long commentPos) {
    // If the leading comments start on different line than the start of node, write new line
    if (pos != commentPos && .getLineOfLocalPositionFromLineMap(lineMap, pos) != .getLineOfLocalPositionFromLineMap(lineMap, commentPos)) {
        _基础环境.writer.writeLine();
    }
}
void emitLeadingComment(long commentPos, long commentEnd, SK 目标种类, bool 有尾随新行, long rangePos) {
    if (_基础环境.currentSourceFile !is ··null!(源文件_)) {
        if (!_基础环境.hasWrittenComment) {
            .emitNewLineBeforeLeadingCommentOfPosition(.getCurrentLineMap(), rangePos, commentPos);
            _基础环境.hasWrittenComment = true;
        }
        .emitPos(commentPos);
        .writeCommentRange(_基础环境.currentSourceFile.内容, .getCurrentLineMap(), commentPos, commentEnd, _基础环境.newLine);
        .emitPos(commentEnd);
    }
    if (有尾随新行) {
        _基础环境.writer.writeLine();
    }
    else if (目标种类 == SK.多行注释) {
        _基础环境.writer.writeSpace(" "d);
    }
}
void emitLeadingCommentsOfPosition(long 开始) {
    if (_基础环境.commentsDisabled || 开始 < 0) {
        return;
    }
    .emitLeadingComments(开始, /*isEmittedNode*/ true);
}
void emitTrailingComments(long 开始) {
    .forEachTrailingCommentToEmit(开始, (整数_ commentPos, 整数_ commentEnd, SK 目标种类, bool 有尾随新行, 整数_ _) {
        SK 种类 = SK.多行注释;
        if (目标种类 == SK.单行注释) {
            种类 = SK.单行注释;
        }
        return .emitTrailingComment(commentPos, commentEnd, 种类, 有尾随新行);
    });
}
void emitTrailingComment(long commentPos, long commentEnd, SK _kind, bool 有尾随新行) {
    // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/
    if (!_基础环境.writer.isAtStartOfLine()) {
        _基础环境.writer.writeSpace(" "d);
    }
    if (_基础环境.currentSourceFile !is ··null!(源文件_)) {
        .emitPos(commentPos);
        .writeCommentRange(_基础环境.currentSourceFile.内容, .getCurrentLineMap(), commentPos, commentEnd, _基础环境.newLine);
        .emitPos(commentEnd);
    }
    if (有尾随新行) {
        _基础环境.writer.writeLine();
    }
}
void emitTrailingCommentsOfPosition(long 开始, bool prefixSpace = ··null!(bool), bool forceNoNewline = ··null!(bool)) {
    if (_基础环境.commentsDisabled) {
        return;
    }
    if (prefixSpace) {
        .forEachTrailingCommentToEmit(开始, (整数_ commentPos, 整数_ commentEnd, SK 目标种类, bool 有尾随新行, 整数_ _) {
            SK 种类 = SK.多行注释;
            if (目标种类 == SK.单行注释) {
                种类 = SK.单行注释;
            }
            return .emitTrailingComment(commentPos, commentEnd, 种类, 有尾随新行);
        });
    }
    else if (forceNoNewline) {
        .forEachTrailingCommentToEmit(开始, (整数_ commentPos, 整数_ commentEnd, SK 目标种类, bool 有尾随新行, 整数_ _) {
            SK 种类 = SK.多行注释;
            if (目标种类 == SK.单行注释) {
                种类 = SK.单行注释;
            }
            return .emitTrailingCommentOfPositionNoNewline(commentPos, commentEnd, 种类);
        });
    }
    else {
        .forEachTrailingCommentToEmit(开始, (整数_ commentPos, 整数_ commentEnd, SK 目标种类, bool 有尾随新行, 整数_ _) {
            SK 种类 = SK.多行注释;
            if (目标种类 == SK.单行注释) {
                种类 = SK.单行注释;
            }
            return .emitTrailingCommentOfPosition(commentPos, commentEnd, 种类, 有尾随新行);
        });
    }
}
void emitTrailingCommentOfPositionNoNewline(long commentPos, long commentEnd, SK 目标种类) {
    // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
    if (_基础环境.currentSourceFile !is ··null!(源文件_)) {
        .emitPos(commentPos);
        .writeCommentRange(_基础环境.currentSourceFile.内容, .getCurrentLineMap(), commentPos, commentEnd, _基础环境.newLine);
        .emitPos(commentEnd);
    }
    if (目标种类 == SK.单行注释) {
        _基础环境.writer.writeLine(); // still write a newline for single-line comments, so closing tokens aren't written on the same line
    }
}
void emitTrailingCommentOfPosition(long commentPos, long commentEnd, SK _kind, bool 有尾随新行) {
    // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
    if (_基础环境.currentSourceFile !is ··null!(源文件_)) {
        .emitPos(commentPos);
        .writeCommentRange(_基础环境.currentSourceFile.内容, .getCurrentLineMap(), commentPos, commentEnd, _基础环境.newLine);
        .emitPos(commentEnd);
    }
    if (有尾随新行) {
        _基础环境.writer.writeLine();
    }
    else {
        _基础环境.writer.writeSpace(" "d);
    }
}
void forEachLeadingCommentToEmit(long 开始, void delegate(long, long, SK, bool, long) cb) {
    // Emit the leading comments only 如果 the container's 开始 doesn't match because the container should take care of emitting these comments
    if ((_基础环境.currentSourceFile !is ··null!(源文件_)) && (_基础环境.containerPos == -1 || 开始 != _基础环境.containerPos)) {
        if (.hasDetachedComments(开始)) {
            .forEachLeadingCommentWithoutDetachedComments(cast(void delegate(long, long, SK, bool, long))(cb));
        }
        else {
            循环每个前方注释范围_2(_基础环境.currentSourceFile.内容, 开始, cast(void delegate(long, long, SK, bool, long))(cb), /*state*/ 开始);
        }
    }
}
void forEachTrailingCommentToEmit(long 结束, void delegate(long, long, SK, bool, long) cb) {
    // Emit the trailing comments only 如果 the container's 结束 doesn't match because the container should take care of emitting these comments
    if ((_基础环境.currentSourceFile !is ··null!(源文件_)) && (_基础环境.containerEnd == -1 || (结束 != _基础环境.containerEnd && 结束 != _基础环境.declarationListContainerEnd))) {
        循环每个尾随注释范围_1(_基础环境.currentSourceFile.内容, 结束, cast(void delegate(long, long, SK, bool, long))(cb));
    }
}
bool hasDetachedComments(long 开始) {
    return (_基础环境.detachedCommentsInfo !is ··null!(分离注释信息_[])) && _基础环境.detachedCommentsInfo.length > 0 && _基础环境.detachedCommentsInfo[_基础环境.detachedCommentsInfo.length - 1].nodePos == 开始;
}
void forEachLeadingCommentWithoutDetachedComments(void delegate(long, long, SK, bool, long) cb) {
    // get the leading comments from detachedPos
    if (_基础环境.currentSourceFile !is ··null!(源文件_)) {
        long 开始 = _基础环境.detachedCommentsInfo[_基础环境.detachedCommentsInfo.length - 1].detachedCommentEndPos;
        if (_基础环境.detachedCommentsInfo.length - 1 != 0) {
            _基础环境.detachedCommentsInfo.length = _基础环境.detachedCommentsInfo.length - 1;
        }
        else {
            _基础环境.detachedCommentsInfo = 返回零值!(分离注释信息_[])();
        }
        循环每个前方注释范围_2(_基础环境.currentSourceFile.内容, 开始, cast(void delegate(long, long, SK, bool, long))(cb), /*state*/ 开始);
    }
}
void emitDetachedCommentsAndUpdateCommentsInfo(文本范围_ range) {
    if (_基础环境.currentSourceFile !is ··null!(源文件_)) {
        分离注释信息_ currentDetachedCommentInfo = .emitDetachedComments(_基础环境.currentSourceFile.内容, .getCurrentLineMap(), cast(写注释函数类型_)(·fd(&.emitComment)), range, _基础环境.newLine, _基础环境.commentsDisabled);
        if (currentDetachedCommentInfo !is ··null!(分离注释信息_)) {
            if (_基础环境.detachedCommentsInfo !is ··null!(分离注释信息_[])) {
                .追加!(分离注释信息_)(_基础环境.detachedCommentsInfo, currentDetachedCommentInfo);
            }
            else {
                _基础环境.detachedCommentsInfo = 创建数组!(分离注释信息_)();
                .追加!(分离注释信息_)(_基础环境.detachedCommentsInfo, currentDetachedCommentInfo);
            }
        }
    }
}
void emitComment(dstring 内容, long[] lineMap, long commentPos, long commentEnd, dstring newLine) {
    .emitPos(commentPos);
    .writeCommentRange(内容, lineMap, commentPos, commentEnd, _基础环境.newLine);
    .emitPos(commentEnd);
}
void setSourceMapSource(源映射范围_ source) {
    if (_基础环境.sourceMapsDisabled) {
        return;
    }
    _基础环境.sourceMapSource = source;
    if (source == _基础环境.mostRecentlyAddedSourceMapSource) {
        // Fast path for when the new source map is the most recently added, in which case
        // we use its captured index without going through the source map generator.
        _基础环境.sourceMapSourceIndex = _基础环境.mostRecentlyAddedSourceMapSourceIndex;
        return;
    }
    if (.isJsonSourceMapSource((cast(源文件_)(source)))) {
        return;
    }
    _基础环境.sourceMapSourceIndex = _基础环境.sourceMapGenerator.addSource((cast(源文件_)(source)).文件名);
    if (_基础环境.inlineSources) {
        _基础环境.sourceMapGenerator.setSourceContent(_基础环境.sourceMapSourceIndex, (cast(源文件_)(source)).内容);
    }
    _基础环境.mostRecentlyAddedSourceMapSource = source;
    _基础环境.mostRecentlyAddedSourceMapSourceIndex = _基础环境.sourceMapSourceIndex;
}
void resetSourceMapSource(源映射范围_ source, long sourceIndex) {
    _基础环境.sourceMapSource = source;
    _基础环境.sourceMapSourceIndex = sourceIndex;
}
bool isJsonSourceMapSource(源文件_ sourceFile) {
    return (sourceFile.文件名 !is null) && (sourceFile.文件名.原型 !is ··null!(dstring)) && 文件扩展名是(sourceFile.文件名, ".json"d);
}
void emitSourceMapsBeforeNode(节点_ node) {
    EmitFlags emitFlags = getEmitFlags(node);
    源映射范围_ sourceMapRange = getSourceMapRange(node);
    // Emit leading sourcemap
    源映射范围_ source; // = sourceMapRange.source || _基础环境.sourceMapSource;
    if ((sourceMapRange !is ··null!(源映射范围_)) && (sourceMapRange.source !is ··null!(文本范围_))) {
        source = (cast(源映射范围_)(sourceMapRange.source));
    }
    else {
        source = _基础环境.sourceMapSource;
    }
    if ((emitFlags & EmitFlags.NoLeadingSourceMap) == 0 && sourceMapRange.开始 >= 0 && (source !is ··null!(源映射范围_))) {
        if (sourceMapRange.source !is ··null!(文本范围_)) {
            .emitSourcePos((cast(源映射范围_)(sourceMapRange.source)), .skipSourceTrivia((cast(源文件_)((cast(文本范围_)(source)))), sourceMapRange.开始));
        }
        else {
            .emitSourcePos(source, .skipSourceTrivia((cast(源文件_)((cast(文本范围_)(source)))), sourceMapRange.开始));
        }
    }
    if ((emitFlags & EmitFlags.NoNestedSourceMaps) != 0) {
        _基础环境.sourceMapsDisabled = true;
    }
}
void emitSourceMapsAfterNode(节点_ node) {
    EmitFlags emitFlags = getEmitFlags(node);
    源映射范围_ sourceMapRange = getSourceMapRange(node);
    if ((emitFlags & EmitFlags.NoNestedSourceMaps) != 0) {
        _基础环境.sourceMapsDisabled = false;
    }
    if ((emitFlags & EmitFlags.NoTrailingSourceMap) == 0 && sourceMapRange.结束 >= 0) {
        if (sourceMapRange.source !is ··null!(文本范围_)) {
            .emitSourcePos((cast(源映射范围_)(sourceMapRange.source)), sourceMapRange.结束);
        }
        else if (_基础环境.sourceMapSource !is ··null!(源映射范围_)) {
            .emitSourcePos(_基础环境.sourceMapSource, sourceMapRange.结束);
        }
    }
}
/**
 * Skips trivia such as comments and white-space that can be optionally overridden by the source-map source
 */
long skipSourceTrivia(源文件_ source, long pos) {
    return 跳过杂项(source.内容, pos, false, false);
}
/**
 * Emits a mapping.
 *
 * If the position is synthetic (undefined or a negative value), no mapping will be
 * created.
 *
 * @param pos The position.
 */
void emitPos(long pos) {
    if (_基础环境.sourceMapsDisabled || pos < 0 || .isJsonSourceMapSource((cast(源文件_)((cast(节点_)((cast(文本范围_)(_基础环境.sourceMapSource)))))))) {
        return;
    }
    ··类型_.行和列_ 行和列 = 获取位置的行和列((cast(源文件_)((cast(节点_)((cast(文本范围_)(_基础环境.sourceMapSource)))))), pos);
    _基础环境.sourceMapGenerator.addMapping(_基础环境.writer.getLine(), _基础环境.writer.getColumn(), _基础环境.sourceMapSourceIndex, 行和列.行, 行和列.列, 
    /*nameIndex*/ ··null!(long));
}
void emitSourcePos(源映射范围_ source, long pos) {
    if (source != _基础环境.sourceMapSource) {
        源映射范围_ savedSourceMapSource = _基础环境.sourceMapSource;
        long savedSourceMapSourceIndex = _基础环境.sourceMapSourceIndex;
        .setSourceMapSource(source);
        .emitPos(pos);
        .resetSourceMapSource(savedSourceMapSource, savedSourceMapSourceIndex);
    }
    else {
        .emitPos(pos);
    }
}
